﻿using System;
using NJabber.Stream.Elements;

namespace NJabber.Client.StanzaFactories
{
    public abstract class StanzaFactory<TParams> where TParams : StanzaParameters
    {
        private IIdGenerator idGenerator;
        private TParams defaultParameters;

        public TParams DefaultParameters
        {
            get { return defaultParameters ?? (defaultParameters = CreateDefaultParameters()); }
        }

        public bool GenerateId { get; set; }

        protected IIdGenerator IdGenerator
        {
            get { return idGenerator ?? (idGenerator = CreateIdGenerator()); }
        }

        private IIdGenerator CreateIdGenerator()
        {
            return new DefaultIdGenerator();
        }

        private TParams CreateDefaultParameters()
        {
            return Activator.CreateInstance<TParams>();
        }

        protected virtual TStanza CreateStanza<TStanza>() where TStanza : Stanza
        {
            return CreateStanza<TStanza>(DefaultParameters);
        }

        protected virtual TStanza CreateStanza<TStanza>(TParams parameters) where TStanza : Stanza
        {
            TStanza stanza = CreateCoreStanza<TStanza>();
            if (GenerateId) stanza.Id = IdGenerator.NewId();
            stanza.Type = parameters.Type;
            stanza.From = parameters.From;
            stanza.To = parameters.To;
            stanza.XmlLang = parameters.XmlLang;
            return stanza;
        }

        protected virtual TStanza CreateCoreStanza<TStanza>() where TStanza : Stanza
        {
            return Activator.CreateInstance<TStanza>();
        }
    }
}
